home *** CD-ROM | disk | FTP | other *** search
/ MIDICraft's MIDINET CD-ROM / MIDICraft's MIDINET CD-ROM.iso / DOSUTILS / MIDICAT.ZIP / MIDICAT.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1997-01-11  |  11.5 KB  |  498 lines

  1. // midicat v1.0 written by Günter Nagler 1996 (gnagler@ihm.tu-graz.ac.at)
  2. // concatenate midi format 0 files
  3. #include "midiio.hpp"
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <ctype.h>
  7.  
  8. char* input = 0;
  9. char* output = 0;
  10.  
  11. #define MAXSONGS   50
  12.  
  13. int songnr = 0;
  14. unsigned long lasttime[MAXSONGS];
  15. int resolution = 0;
  16.  
  17. MidiWrite* write = 0;
  18.  
  19. class MidiCat : public MidiRead
  20. {
  21. public:
  22.   MidiCat(char* name);
  23.  
  24.   virtual void head(unsigned version, unsigned tracks, unsigned unitsperbeat);
  25.   virtual void track(int trackno, long length, int channel);
  26.   virtual void endtrack(int trackno);
  27.  
  28.   virtual void text(int what, int len, char* whattext, unsigned char* txt);
  29.   virtual void meta(int what, int len, unsigned char* data);
  30.   virtual void end();
  31.   virtual void tact(int nom, int denom, int v1, int v2);
  32.   virtual void tempo(unsigned long ticks);
  33.   virtual void program(int prg, int channel);
  34.   virtual void control(int channel, int what, int value);
  35.   virtual void highbank(int channel, int val);
  36.   virtual void wheel(int channel, int val);
  37.   virtual void breath(int channel, int val);
  38.   virtual void foot(int channel, int val);
  39.   virtual void portamentotime(int channel, int val);
  40.   virtual void data(int channel, int val);
  41.   virtual void volume(int channel, int val);
  42.   virtual void balance(int channel, int val);
  43.   virtual void expression(int channel, int val);
  44.   virtual void lowbank(int channel, int val);
  45.   virtual void hold(int channel, int val);
  46.   virtual void reverb(int channel, int val);
  47.   virtual void chorus(int channel, int val);
  48.   virtual void datainc(int channel, int val);
  49.   virtual void datadec(int channel, int val);
  50.   virtual void noteon(int channel, int note, int vel);
  51.   virtual void noteoff(int channel, int note, int vel);
  52.   virtual void time(unsigned long ticks);
  53.   virtual void pitchbend(int channel, int val);
  54.   virtual void polyaftertouch(int channel, int note, int val);
  55.   virtual void aftertouch(int channel, int val);
  56.   virtual void songpos(unsigned pos);
  57.   virtual void songselect(unsigned char song);
  58.   virtual void tunerequest();
  59.   virtual void timingclock();
  60.   virtual void start();
  61.   virtual void cont();
  62.   virtual void stop();
  63.   virtual void activesense();
  64.   virtual void sysex(int syslen, unsigned char* sysdata);
  65.   virtual void error(const char* msg);
  66.   virtual void warning(const char* msg);
  67.  
  68.   virtual void percent(int perc);
  69. };
  70.  
  71. MidiCat::MidiCat(char* name) : MidiRead(name)
  72. {
  73. }
  74.  
  75. void MidiCat::head(unsigned version, unsigned tracks, unsigned unitsperbeat)
  76. {
  77.   if (!write)
  78.   {
  79.     printf("%s: format %d, %d tracks, resolution %d\n", midiname_, version, tracks, unitsperbeat);
  80.     if (!resolution)
  81.       resolution = unitsperbeat;
  82.     else if (resolution != unitsperbeat)
  83.       // common multiplyer of resolution and unitsperbeat
  84.     {
  85.     int divider = 1;
  86.  
  87.       for (int d = 2; d <= resolution && d <= unitsperbeat; d++)
  88.     if (resolution % d == 0 && unitsperbeat % d == 0)
  89.       divider = d;
  90.       // greatest common divider
  91.       if (divider == 1)
  92.       {
  93.     if (unitsperbeat > divider)
  94.       resolution = unitsperbeat;
  95.       }
  96.       else
  97.     resolution *= unitsperbeat / divider;
  98.     }
  99.   }
  100. }
  101.  
  102. void MidiCat::track(int trackno, long length, int channel)
  103. {
  104. }
  105.  
  106. void MidiCat::endtrack(int trackno)
  107. {
  108. }
  109.  
  110. void MidiCat::text(int what, int len, char* whattext, unsigned char* txt)
  111. {
  112.   if (write && getcurunit() <= lasttime[songnr])
  113.     write->text(what, len, txt);
  114. }
  115.  
  116. void MidiCat::meta(int what, int len, unsigned char* data)
  117. {
  118.   if (write && getcurunit() <= lasttime[songnr])
  119.     write->meta(what, len, data);
  120. }
  121.  
  122. void MidiCat::end()
  123. {
  124.   if (write)
  125.   {
  126.     write->cleardelta();
  127.     write->time(resolution);  // 1 tact pause!
  128.   }
  129. }
  130.  
  131. void MidiCat::tact(int nom, int denom, int v1, int v2)
  132. {
  133.   if (write && getcurunit() <= lasttime[songnr])
  134.     write->tact(nom, denom, v1, v2);
  135. }
  136.  
  137. void MidiCat::tempo(unsigned long ticks)
  138. {
  139.   if (write && getcurunit() <= lasttime[songnr])
  140.     write->tempo(ticks);
  141. }
  142.  
  143. void MidiCat::time(unsigned long ticks)
  144. {
  145.   if (write && getcurunit() <= lasttime[songnr])
  146.   {
  147.     if (unitsperbeat_ != resolution)
  148.     {
  149.       ticks = (int)(((long)resolution * (long)ticks) / (long)unitsperbeat_);
  150.     }
  151.     write->time(ticks);
  152.   }
  153. }
  154.  
  155. void MidiCat::program(int channel, int prg)
  156. {
  157.   if (write && getcurunit() <= lasttime[songnr])
  158.     write->program(channel, prg);
  159. }
  160.  
  161. void MidiCat::control(int channel, int what, int value)
  162. {
  163.   if (write && getcurunit() <= lasttime[songnr])
  164.     write->control(channel, what, value);
  165. }
  166.  
  167. void MidiCat::balance(int channel, int val)
  168. {
  169.   if (write && getcurunit() <= lasttime[songnr])
  170.     write->balance(channel, val);
  171. }
  172.  
  173. void MidiCat::highbank(int channel, int val)
  174. {
  175.   if (write && getcurunit() <= lasttime[songnr])
  176.     write->highbank(channel, val);
  177. }
  178.  
  179. void MidiCat::wheel(int channel, int val)
  180. {
  181.   if (write && getcurunit() <= lasttime[songnr])
  182.     write->wheel(channel, val);
  183. }
  184.  
  185. void MidiCat::breath(int channel, int val)
  186. {
  187.   if (write && getcurunit() <= lasttime[songnr])
  188.     write->breath(channel, val);
  189. }
  190.  
  191. void MidiCat::foot(int channel, int val)
  192. {
  193.   if (write && getcurunit() <= lasttime[songnr])
  194.     write->foot(channel, val);
  195. }
  196.  
  197. void MidiCat::portamentotime(int channel, int val)
  198. {
  199.   if (write && getcurunit() <= lasttime[songnr])
  200.     write->portamentotime(channel, val);
  201. }
  202.  
  203. void MidiCat::data(int channel, int val)
  204. {
  205.   if (write && getcurunit() <= lasttime[songnr])
  206.     write->data(channel, val);
  207. }
  208.  
  209. void MidiCat::volume(int channel, int val)
  210. {
  211.   if (write && getcurunit() <= lasttime[songnr])
  212.     write->volume(channel, val);
  213. }
  214.  
  215. void MidiCat::expression(int channel, int val)
  216. {
  217.   if (write && getcurunit() <= lasttime[songnr])
  218.     write->expression(channel, val);
  219. }
  220.  
  221. void MidiCat::lowbank(int channel, int val)
  222. {
  223.   if (write && getcurunit() <= lasttime[songnr])
  224.     write->lowbank(channel, val);
  225. }
  226.  
  227. void MidiCat::hold(int channel, int val)
  228. {
  229.   if (write && getcurunit() <= lasttime[songnr])
  230.     write->hold(channel, val);
  231. }
  232.  
  233. void MidiCat::reverb(int channel, int val)
  234. {
  235.   if (write && getcurunit() <= lasttime[songnr])
  236.     write->reverb(channel, val);
  237. }
  238.  
  239. void MidiCat::chorus(int channel, int val)
  240. {
  241.   if (write && getcurunit() <= lasttime[songnr])
  242.     write->chorus(channel, val);
  243. }
  244.  
  245. void MidiCat::datainc(int channel, int val)
  246. {
  247.   if (write && getcurunit() <= lasttime[songnr])
  248.     write->datainc(channel, val);
  249. }
  250.  
  251. void MidiCat::datadec(int channel, int val)
  252. {
  253.   if (write && getcurunit() <= lasttime[songnr])
  254.     write->datadec(channel, val);
  255. }
  256.  
  257. void MidiCat::noteon(int channel, int note, int vel)
  258. {
  259.   if (write)
  260.   {
  261.     if(getcurunit() <= lasttime[songnr])
  262.       write->noteon(channel, note, vel);
  263.   }
  264.   else
  265.     lasttime[songnr] = getcurunit();
  266. }
  267.  
  268. void MidiCat::noteoff(int channel, int note, int vel)
  269. {
  270.   if (write)
  271.   {
  272.     if(getcurunit() <= lasttime[songnr])
  273.       write->noteoff(channel, note, vel);
  274.   }
  275.   else
  276.     lasttime[songnr] = getcurunit();
  277. }
  278.  
  279. void MidiCat::pitchbend(int channel, int val)
  280. {
  281.   if (write)
  282.   {
  283.     if(getcurunit() <= lasttime[songnr])
  284.       write->pitchbend(channel, val);
  285.   }
  286.   else
  287.     lasttime[songnr] = getcurunit();
  288. }
  289.  
  290. void MidiCat::polyaftertouch(int channel, int note, int val)
  291. {
  292.   if (write)
  293.   {
  294.     if(getcurunit() <= lasttime[songnr])
  295.        write->polyaftertouch(channel, note, val);
  296.   }
  297.   else
  298.     lasttime[songnr] = getcurunit();
  299. }
  300.  
  301. void MidiCat::aftertouch(int channel, int val)
  302. {
  303.   if (write)
  304.   {
  305.     if(getcurunit() <= lasttime[songnr])
  306.       write->aftertouch(channel, val);
  307.   }
  308.   else
  309.     lasttime[songnr] = getcurunit();
  310. }
  311.  
  312. void MidiCat::songpos(unsigned pos)
  313. {
  314.   if (write && getcurunit() <= lasttime[songnr])
  315.     write->songpos(pos);
  316. }
  317.  
  318. void MidiCat::songselect(unsigned char song)
  319. {
  320.   if (write && getcurunit() <= lasttime[songnr])
  321.     write->songselect(song);
  322. }
  323.  
  324. void MidiCat::tunerequest()
  325. {
  326.   if (write && getcurunit() <= lasttime[songnr])
  327.     write->tunerequest();
  328. }
  329.  
  330. void MidiCat::timingclock()
  331. {
  332.   if (write && getcurunit() <= lasttime[songnr])
  333.     write->timingclock();
  334. }
  335.  
  336. void MidiCat::start()
  337. {
  338.   if (write && getcurunit() <= lasttime[songnr])
  339.     write->start();
  340. }
  341.  
  342. void MidiCat::cont()
  343. {
  344.   if (write && getcurunit() <= lasttime[songnr])
  345.     write->cont();
  346. }
  347.  
  348. void MidiCat::stop()
  349. {
  350.   if (write && getcurunit() <= lasttime[songnr])
  351.     write->stop();
  352. }
  353.  
  354. void MidiCat::activesense()
  355. {
  356.   if (write && getcurunit() <= lasttime[songnr])
  357.     write->activesense();
  358. }
  359.  
  360. void MidiCat::sysex(int syslen, unsigned char* sysdata)
  361. {
  362.   if (write && getcurunit() <= lasttime[songnr])
  363.     write->sysex(syslen, sysdata);
  364. }
  365.  
  366. void MidiCat::percent(int perc)
  367. {
  368.     fprintf(stderr, "%-3d%%\r", perc);
  369. }
  370.  
  371. void MidiCat::error(const char* msg)
  372. {
  373.   printf("Error: %s\n", msg);
  374.   exit(1);
  375. }
  376.  
  377. void MidiCat::warning(const char* msg)
  378. {
  379.   printf("Warning: %s\n", msg);
  380. }
  381.  
  382. int scanmidi(char* input)
  383. {
  384.   lasttime[songnr] = 0; // find end of
  385.  
  386.   MidiCat midi(input);
  387.   if (!midi.getf())
  388.   {
  389.     perror(input);
  390.     return 1;
  391.   }
  392.   midi.options_ = OPTION_NOMETAEVENTS | OPTION_NOSYSEVENTS | OPTION_NOCONTROLS;
  393.   if (!midi.run())
  394.   {
  395.     fprintf(stderr, "%s is not a correct midi\n", input);
  396.     return 1;
  397.   }
  398.   if (midi.version_ != 0)
  399.   {
  400.     fprintf(stderr, "%s is format %d midi!\nConvert it to format 0 using midi%dto0\n",
  401.        input, midi.version_, midi.version_);
  402.     return 1;
  403.   }
  404.   return 0;
  405. }
  406.  
  407. void usage()
  408. {
  409.   fprintf(stderr, "MidiCat concatenates midi format 0 files to play sequentially\n");
  410.   fprintf(stderr, "usage: MidiCat file1.mid file2.mid ... result.mid\n");
  411.   exit(1);
  412. }
  413.  
  414. int main(int argc, char**argv)
  415. {
  416.   argc--; argv++;
  417.   while (argc > 0 && **argv == '-')
  418.   {
  419.     fprintf(stderr, "invalid option %s\n", *argv);
  420.     argc--; argv++;
  421.     usage();
  422.   }
  423.   if (argc < 2)
  424.     usage();
  425.  
  426.   output = argv[argc - 1];
  427.   argc--;
  428.   for (songnr = 0; songnr < argc; songnr++)
  429.   if (strcmp(argv[songnr], output) == 0)
  430.   {
  431.     fprintf(stderr, "cannot convert midi to one of the input files\n");
  432.     return 1;
  433.   }
  434.   FILE* testf = fopen(output, "r");
  435.   if (testf)
  436.   {
  437.     fclose(testf);
  438.     fprintf(stderr, "output file %s already existing. aborting...\n", output);
  439.     return 1;
  440.   }
  441.  
  442.   // test if all input files are available
  443.   for (songnr = 0; songnr < argc; songnr++)
  444.   {
  445.     if (scanmidi(input=argv[songnr]))
  446.       return 1;
  447.   }
  448.   write = new MidiWrite(output);
  449.   if (!write)
  450.   {
  451.     fprintf(stderr, "out of memory\n");
  452.     return 1;
  453.   }
  454.   if (!write->getf())
  455.   {
  456.     perror(output);
  457.     return 1;
  458.   }
  459.   write->head(0, 1, resolution);
  460.   write->track();
  461.  
  462.   for (songnr = 0; songnr < argc; songnr++)
  463.   {
  464.   static char* seperator = "-- midi file added by midicat --";
  465.  
  466.     write->text(meta_marker, strlen(seperator), seperator);
  467.     // initialize new midi parameters
  468.     write->tact(4, 4, 24, 8);
  469.     write->tempo(tempo_120bpm);
  470.     for (int ch = 0; ch < 16; ch++)
  471.     {
  472.       if (ch != gm_drumchannel)
  473.     write->program(ch, 0);  // piano
  474.       write->volume(ch, volume_full);
  475.       write->balance(ch, balance_center);
  476.       write->reverb(ch, 13);
  477.       write->chorus(ch, 13);
  478.     }
  479.  
  480.     MidiCat midi(input = argv[songnr]);
  481.     if (!midi.getf())
  482.     {
  483.       perror(input);
  484.       return 1;
  485.     }
  486.     midi.options_ = OPTION_NOCONTROLS|OPTION_NOSYSEVENTS;
  487.     if (!midi.run())
  488.       fprintf(stderr, "%s: midi read error at %04lX\n", input, midi.getpos());
  489.   }
  490.   write->end();
  491.  
  492.   delete write; write = 0;
  493.   printf("output written to %s:\n", output);
  494.   songnr = 0;
  495.   scanmidi(output);
  496.   return 0;
  497. }
  498.